package edu.gatech.app4args;

import edu.gatech.app4args.utils.CustomNodeRenderer;
import edu.gatech.app4args.utils.CustomTreeNode;
import edu.gatech.app4args.utils.CompendiumNode;
import edu.gatech.app4args.utils.NodeDropHandler;
import edu.gatech.app4args.utils.PptxCreator;
import edu.gatech.app4args.utils.SlideData;
import edu.gatech.app4args.utils.XMLFileFilter;
import edu.gatech.app4args.utils.XMLImporter;

import java.awt.Cursor;
import java.awt.Desktop;

import java.io.File;

import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
//import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;

/**
 * The main application window. This class inits all sub views and controls the
 * import of xml files and export of pptx/odp files.
 *
 * @author Andrew Lunsford
 */
public class Main extends javax.swing.JFrame implements TreeWillExpandListener{
	/** A pointer to the file being imported / exported */
	private File currentFile;
	/** The map of nodes imported from the Compendium xml file */
	private HashMap<String, CompendiumNode> nodeMap;
	/** An array list to hold all user created slides */
	// TODO changed to public for rushed testing, change back to private
	public ArrayList<SlideData> slides;
	/** A pointer to the current slide */
	private SlideData currentSlide;

        // Main Sections
	//private JTree nodeTree;
	/** Information panel */
	private SlideInfoPanel slideInfoPanel;
	/** Content panel */
	private SlideContentPanel slideContentPanel;
	/** Overview slides panel */
	private OverviewPanel overviewPanel;

	/** Creates new form Main */
	public Main() {
		initComponents();
		customSetup();
		nodeMap = new HashMap<String, CompendiumNode>();
		slides = new ArrayList<SlideData>();
	}

	Main(App4Args aThis) {
		this();
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        libraryLabel = new javax.swing.JLabel();
        libraryPane = new javax.swing.JScrollPane();
        nodeTree = new javax.swing.JTree();
        slideContentLabel = new javax.swing.JLabel();
        slideContentPane = new javax.swing.JScrollPane();
        slideInfoLabel = new javax.swing.JLabel();
        slideInfoPane = new javax.swing.JScrollPane();
        slideInfoTagBox = new javax.swing.JTextField();
        overviewLabel = new javax.swing.JLabel();
        overviewPane = new javax.swing.JScrollPane();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        importFMI = new javax.swing.JMenuItem();
        exportFMI = new javax.swing.JMenuItem();
        saveFMI = new javax.swing.JMenuItem();
        exitFMI = new javax.swing.JMenuItem();
        editMenu = new javax.swing.JMenu();
        reverseEMI = new javax.swing.JMenuItem();
        slideMenu = new javax.swing.JMenu();
        newSMI = new javax.swing.JMenuItem();
        duplicateSMI = new javax.swing.JMenuItem();
        deleteSMI = new javax.swing.JMenuItem();
        helpMenu = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        app4argsHMI = new javax.swing.JMenuItem();
        compendiumHMI = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(edu.gatech.app4args.App4Args.class).getContext().getResourceMap(Main.class);
        setBackground(resourceMap.getColor("Form.background")); // NOI18N
        setForeground(resourceMap.getColor("Form.foreground")); // NOI18N
        setName("Form"); // NOI18N
        setResizable(false);

        libraryLabel.setFont(resourceMap.getFont("libraryLabel.font")); // NOI18N
        libraryLabel.setText(resourceMap.getString("libraryLabel.text")); // NOI18N
        libraryLabel.setName("libraryLabel"); // NOI18N

        libraryPane.setName("libraryPane"); // NOI18N

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("Import a Compendium XML file to get started");
        nodeTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        nodeTree.setName("nodeTree"); // NOI18N
        nodeTree.setShowsRootHandles(true);
        libraryPane.setViewportView(nodeTree);

        slideContentLabel.setFont(resourceMap.getFont("slideContentLabel.font")); // NOI18N
        slideContentLabel.setText(resourceMap.getString("slideContentLabel.text")); // NOI18N
        slideContentLabel.setName("slideContentLabel"); // NOI18N

        slideContentPane.setHorizontalScrollBar(null);
        slideContentPane.setName("slideContentPane"); // NOI18N

        slideInfoLabel.setFont(resourceMap.getFont("slideInfoLabel.font")); // NOI18N
        slideInfoLabel.setText(resourceMap.getString("slideInfoLabel.text")); // NOI18N
        slideInfoLabel.setName("slideInfoLabel"); // NOI18N

        slideInfoPane.setHorizontalScrollBar(null);
        slideInfoPane.setName("slideInfoPane"); // NOI18N

        slideInfoTagBox.setText(resourceMap.getString("slideInfoTagBox.text")); // NOI18N
        slideInfoTagBox.setDragEnabled(false);
        slideInfoTagBox.setName("slideInfoTagBox"); // NOI18N

        overviewLabel.setFont(resourceMap.getFont("overviewLabel.font")); // NOI18N
        overviewLabel.setText(resourceMap.getString("overviewLabel.text")); // NOI18N
        overviewLabel.setName("overviewLabel"); // NOI18N

        overviewPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        overviewPane.setName("overviewPane"); // NOI18N

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        importFMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_I, java.awt.event.InputEvent.CTRL_MASK));
        importFMI.setText(resourceMap.getString("importFMI.text")); // NOI18N
        importFMI.setName("importFMI"); // NOI18N
        importFMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importXMLPressed(evt);
            }
        });
        fileMenu.add(importFMI);

        exportFMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E, java.awt.event.InputEvent.CTRL_MASK));
        exportFMI.setText(resourceMap.getString("exportFMI.text")); // NOI18N
        exportFMI.setName("exportFMI"); // NOI18N
        exportFMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportPresentatinPressed(evt);
            }
        });
        fileMenu.add(exportFMI);

        saveFMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        saveFMI.setText(resourceMap.getString("saveFMI.text")); // NOI18N
        saveFMI.setEnabled(false);
        saveFMI.setName("saveFMI"); // NOI18N
        fileMenu.add(saveFMI);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(edu.gatech.app4args.App4Args.class).getContext().getActionMap(Main.class, this);
        exitFMI.setAction(actionMap.get("quit")); // NOI18N
        exitFMI.setName("exitFMI"); // NOI18N
        fileMenu.add(exitFMI);

        menuBar.add(fileMenu);

        editMenu.setText(resourceMap.getString("editMenu.text")); // NOI18N

        reverseEMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        reverseEMI.setText(resourceMap.getString("reverseEMI.text")); // NOI18N
        reverseEMI.setName("reverseEMI"); // NOI18N
        reverseEMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                reverseLinks(evt);
            }
        });
        editMenu.add(reverseEMI);

        menuBar.add(editMenu);

        slideMenu.setText(resourceMap.getString("slideMenu.text")); // NOI18N
        slideMenu.setName("slideMenu"); // NOI18N

        newSMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        newSMI.setText(resourceMap.getString("newSMI.text")); // NOI18N
        newSMI.setName("newSMI"); // NOI18N
        newSMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newSlidePressed(evt);
            }
        });
        slideMenu.add(newSMI);

        duplicateSMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_D, java.awt.event.InputEvent.CTRL_MASK));
        duplicateSMI.setText(resourceMap.getString("duplicateSMI.text")); // NOI18N
        duplicateSMI.setEnabled(false);
        duplicateSMI.setName("duplicateSMI"); // NOI18N
        slideMenu.add(duplicateSMI);

        deleteSMI.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DELETE, 0));
        deleteSMI.setText(resourceMap.getString("deleteSMI.text")); // NOI18N
        deleteSMI.setEnabled(false);
        deleteSMI.setName("deleteSMI"); // NOI18N
        slideMenu.add(deleteSMI);

        menuBar.add(slideMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        jMenuItem1.setText(resourceMap.getString("jMenuItem1.text")); // NOI18N
        jMenuItem1.setName("jMenuItem1"); // NOI18N
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        helpMenu.add(jMenuItem1);

        app4argsHMI.setText(resourceMap.getString("app4argsHMI.text")); // NOI18N
        app4argsHMI.setName("app4argsHMI"); // NOI18N
        app4argsHMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                helpApp4ArgsManual(evt);
            }
        });
        helpMenu.add(app4argsHMI);

        compendiumHMI.setText(resourceMap.getString("compendiumHMI.text")); // NOI18N
        compendiumHMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                helpCompendium(evt);
            }
        });
        helpMenu.add(compendiumHMI);

        menuBar.add(helpMenu);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(libraryPane, javax.swing.GroupLayout.PREFERRED_SIZE, 330, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(libraryLabel))
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(slideContentLabel)
                                    .addComponent(overviewLabel))
                                .addGap(288, 288, 288))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(slideContentPane, javax.swing.GroupLayout.PREFERRED_SIZE, 442, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(slideInfoLabel)
                            .addComponent(slideInfoPane, javax.swing.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(slideInfoTagBox, javax.swing.GroupLayout.PREFERRED_SIZE, 211, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(28, 28, 28))))
                    .addComponent(overviewPane, javax.swing.GroupLayout.DEFAULT_SIZE, 738, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(slideContentLabel)
                    .addComponent(slideInfoLabel)
                    .addComponent(libraryLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(libraryPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 602, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(slideInfoTagBox, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(slideInfoPane, javax.swing.GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE))
                            .addComponent(slideContentPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 408, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(overviewLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(overviewPane, javax.swing.GroupLayout.PREFERRED_SIZE, 123, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(40, 40, 40)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	/**
	 * Calls custom initialization methods.
	 */
	private void customSetup(){
		// section setup
		//initLibrary();
		initSlideContent();
		initSlideInfo();
		initOverview();
	}

	/**
	 * Called when the Import MenuItem is selected in the File Menu.
	 * Opens a FileChooser to allow the user to select which Compendium xml
	 * file to import.
	 *
	 * @param evt
	 */
	private void importXMLPressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importXMLPressed
		JFileChooser fileChooser = new JFileChooser();
		fileChooser.setName("fileChooser");
		fileChooser.setFileFilter(new XMLFileFilter());

		int returnVal = fileChooser.showOpenDialog(this);
		if(returnVal == JFileChooser.APPROVE_OPTION){
			currentFile = fileChooser.getSelectedFile();
			this.loadMap(true);
		}
		fileChooser = null;
	}//GEN-LAST:event_importXMLPressed

	/**
	 * Called when the New Slide MenuItem is selected in the Slide Menu.
	 * Opens an OptionPane with the NewSlide panel to allow the user to choose
	 * which type of slide they wish to create. Once they select one and click
	 * Create, it calls #addNewSlide
	 *
	 * @param evt
	 */
	private void newSlidePressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newSlidePressed
		NewSlide newSlidePanel = new NewSlide();
		Object[] options = {"Create","Cancel"};
		int result = JOptionPane.showOptionDialog(this, newSlidePanel, "New slide type",
				JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
		if(result == 0 && newSlidePanel.getSelected()>0){
			this.addNewSlide(newSlidePanel.getSelected());
		}
	}//GEN-LAST:event_newSlidePressed

	/**
	 * Used to reimport the Compendium xml file, this time building the links
	 * in reverse.
	 *
	 * @param evt
	 */
	private void reverseLinks(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reverseLinks
		this.loadMap(false);
	}//GEN-LAST:event_reverseLinks

	/**
	 * Calls a FileChooser to allow the user to select where to save the
	 * generated Pptx/Odp file, and passes the slides to the PptxCreator
	 * for parsing and creation of the output file.
	 *
	 * @param evt
	 */
	private void exportPresentatinPressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportPresentatinPressed
		// check that there is a presentation first
		if(slides.size()>0){
			JFileChooser fileChooser = new JFileChooser();
			fileChooser.setName("fileChooser");
			//fileChooser.setFileFilter(new XMLFileFilter());

			fileChooser.setSelectedFile(new File("presentation.pptx"));
			int returnVal = fileChooser.showSaveDialog(this);
			if(returnVal == JFileChooser.APPROVE_OPTION){
				System.out.println("Main> save this presentation!!!: "+fileChooser.getSelectedFile());
				PptxCreator presMaker = new PptxCreator();
				// TODO show progress bar or something to indicate saving the pptx takes FOREVER
				// TODO catch return and display success or failure message
				presMaker.savePresentation(fileChooser.getSelectedFile(), slides);
			}
			fileChooser = null;
		}else{
			// show dialog
			JOptionPane.showMessageDialog(this, "Try making a presentation first", "Error", JOptionPane.INFORMATION_MESSAGE);
		}

	}//GEN-LAST:event_exportPresentatinPressed

	private void helpApp4ArgsManual(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_helpApp4ArgsManual
		this.openBrowser("http://code.google.com/p/app4args/wiki/UserManual");
	}//GEN-LAST:event_helpApp4ArgsManual

	private void helpCompendium(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_helpCompendium
		this.openBrowser("http://compendium.open.ac.uk/institute/index.htm");
	}//GEN-LAST:event_helpCompendium

	private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
		SmartArt smartart = new SmartArt();
		smartart.setVisible(true);
	}//GEN-LAST:event_jMenuItem1ActionPerformed

	/**
	 * Opens the url in the default operating system browser.
	 *
	 * @param url the url to open in the browser
	 */
	private void openBrowser(String url){
		boolean support = true;
		if( !java.awt.Desktop.isDesktopSupported() ) {
            System.err.println( "Desktop is not supported (fatal)" );
			support = false;
        }

        Desktop desktop = Desktop.getDesktop();
        if( !desktop.isSupported( java.awt.Desktop.Action.BROWSE ) ) {
            System.err.println( "Desktop doesn't support the browse action (fatal)" );
			support = false;
        }
		if(support){
			try{
				java.net.URI uri = new java.net.URI( url );
				desktop.browse( uri );
			}catch( Exception e ){
				System.err.println( e.getMessage() );
			}
		}
	}

	/**
	 * Calls upong XMLImporter to generate the node map from the Compendium xml
	 * file. Once the node map is copied, it calls importMapToTree().
	 *
	 * @param reverse if true, build links the Compendium way
	 */
	private void loadMap(boolean reverse){
		if(currentFile != null){
			XMLImporter xmlImport = new XMLImporter(reverse);
			if (xmlImport.createMap(currentFile)) {
				nodeMap = xmlImport.getNodeMap();
				this.importMapToTree();
			} else {
				// TODO display popup error
				System.err.println("NODE MAP IS EMPTY ZOMGWTFFFF...");
				/*
				saySomething("You are about to expand node ", e);
				int n = JOptionPane.showOptionDialog(
				this, willExpandText, willExpandTitle,
				JOptionPane.YES_NO_OPTION,
				JOptionPane.QUESTION_MESSAGE,
				null,
				willExpandOptions,
				willExpandOptions[1]);
				 */
			}
			xmlImport = null;
		}
	}

	/**
	 * Sets up the nodeTree with custom options and custom cell renderer.
	 * Also adds a custom transfer handler for the dragging and dropping of
	 * nodes from the tree to the slide content panel. Loads the Root viewref
	 * and hides it, then loads 3 levels deep. All subsequent loads are done
	 * as needed when a tree node is expanded.
	 */
	private void importMapToTree() {
		nodeTree.removeAll();
		nodeTree.setRootVisible(false);
		nodeTree.setShowsRootHandles(true);
		nodeTree.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		nodeTree.addTreeWillExpandListener(this);
		nodeTree.setCellRenderer(new CustomNodeRenderer());
		nodeTree.setDragEnabled(true);
		nodeTree.setTransferHandler(new NodeDropHandler(TransferHandler.COPY));
		// create root and add 3 levels deep
		CustomTreeNode root = new CustomTreeNode(nodeMap.get("root"));
		loadChildren(root, 3);
		// TODO expand children
		nodeTree.setModel(new DefaultTreeModel(root));
	}

	/**
	 * Recursively loads the children nodes for a parent node, up to a certain
	 * depth as specified by the depth parameter.
	 *
	 * @param parent The node for which to load its children
	 * @param depth The number of levels deep to iterate
	 */
	private void loadChildren(CustomTreeNode parent, int depth){
		CompendiumNode pNode = parent.getCNode();
		CompendiumNode cNode;
		CustomTreeNode child;
		for (String key1 : pNode.getChildren()){
			// create and add
			cNode = nodeMap.get(key1);
			child = new CustomTreeNode(cNode);
			if(!parent.childExists(child)){
				parent.add(child);
			}
			// check for children
			if(!cNode.getChildren().isEmpty() && --depth > 0){
				loadChildren(child, depth);
			}
		}
	}

	/**
	 * When a tree node expands, its childrens' children are loaded.
	 *
	 * @param e
	 * @throws ExpandVetoException
	 */
	public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException{
		CustomTreeNode tNode = (CustomTreeNode)e.getPath().getLastPathComponent();
		CompendiumNode cNode = tNode.getCNode();
		if(tNode.getChildCount()>0){
			int i = 0;
			while(i < tNode.getChildCount()){
				loadChildren((CustomTreeNode)tNode.getChildAt(i), 1);
				i++;
			}
		}
	}

	/**
	 * Nothing to do on collapse. Children could be unloaded, but are not at
	 * this time.
	 *
	 * @param e
	 * @throws ExpandVetoException
	 */
	public void treeWillCollapse(TreeExpansionEvent e) throws ExpandVetoException{
		
	}

	// TODO changed to public for testing, change back to private
	/**
	 * Creates a new SlideData object and adds it to the slides array. All
	 * panels are loaded with the correct fields for that slide type.
	 * @param slidetype
	 */
	public void addNewSlide(int slidetype){
		currentSlide = new SlideData(slidetype);
		slides.add(currentSlide);
		slideContentPanel.load(currentSlide,slides.size()-1);
		slideInfoPanel.load(currentSlide, slides.size()-1);
		overviewPanel.addOverviewSlide(this, slidetype, slides.size());
	}

	// TODO switch to treeNode setup via code
	/*
	private void initLibrary(){
		//nodeTree.setName("nodeTree");
		nodeTree = new JTree();
        nodeTree.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		nodeTree.setRootVisible(false);
		nodeTree.setShowsRootHandles(true);
		nodeTree.addTreeWillExpandListener(this);
		nodeTree.setCellRenderer(new CustomNodeRenderer());
        libraryPane.setViewportView(nodeTree);
	}
	*/

	/**
	 * Custom initialization for SlideContentPanel.
	 */
	private void initSlideContent(){
		slideContentPanel = new SlideContentPanel(this);
        slideContentPane.setViewportView(slideContentPanel);
	}

	/**
	 * Custom initialization for SlideInfoPanel.
	 */
	private void initSlideInfo(){
		slideInfoPanel = new SlideInfoPanel(this);
		slideInfoPane.setViewportView(slideInfoPanel);
	}

	/**
	 * Custom initialization for OverviewPanel
	 */
	private void initOverview(){
		overviewPanel = new OverviewPanel(this);
		overviewPane.setViewportView(overviewPanel);
	}

	/**
	 * When a new slide is selected, all three panels must be updated to reflect
	 * the new information.
	 *
	 * @param slideNumber the slide to load
	 */
	public void slideSelected(int slideNumber){
		if(currentSlide!=slides.get(slideNumber)){
			currentSlide = slides.get(slideNumber);
			currentSlide.printString();
			slideContentPanel.load(currentSlide, slideNumber);
			slideInfoPanel.load(currentSlide,slideNumber);
			overviewPanel.setCurrentSlide(slideNumber);
		}
	}

	/**
	 * Called from a SlideInfoSection. The specified slide and section will
	 * be updated to reflect the users selected list style.
	 *
	 * @param slideNumber the slide in the slides array to update
	 * @param section the section of the slide to update
	 * @param liststyle the list style to be applied
	 */
	public void updateListStyle(int slideNumber, int section, int liststyle){
		slides.get(slideNumber).getSection(section).setLStyle(liststyle);
	}

	/**
	 * Called from a SlideInfoSection. The specified slide and section will
	 * be updated to reflect the users selected Smart Art style.
	 *
	 * @param slideNumber the slide in the slides array to update
	 * @param section the section of the slide to update
	 * @param saStyle the SmartArt style to set
	 */
	public void updateSmartArt(int slideNumber, int section, int saStyle){
		slides.get(slideNumber).getSection(section).setSmartArt(saStyle);
	}

	/**
	 * Called from SlideContentSection. The specified slide and section will
	 * have the label data from a CompendiumNode added to it.
	 *
	 * @param slideNumber the slide to update
	 * @param section the section to update
	 * @param key the CompendiumNode to get the data from
	 * @return true if the slide was successfully updated
	 */
	public boolean addSlideData(int slideNumber, int section, String key){
		System.out.println("Main> adding slide: "+slideNumber);
		return slides.get(slideNumber).getSection(section).addContent(nodeMap.get(key).getLabel());
	}

	/**
	 * Gets a CompendiumNode from the nodeMap.
	 *
	 * @param key the node to retrieve
	 * @return the CompendiumNode with that key
	 */
	public CompendiumNode getNode(String key){
		return nodeMap.get(key);
	}

	/**
	 * Runs the class.
	 * 
	 * @param args the command line arguments
	 */
	public static void main(String args[]) {
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				new Main().setVisible(true);
			}
		});
	}

	public ArrayList<SlideData> getSlides() {
		return slides;
	}

	public void setSlides(ArrayList<SlideData> slides) {
		this.slides = slides;
	}
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem app4argsHMI;
    private javax.swing.JMenuItem compendiumHMI;
    private javax.swing.JMenuItem deleteSMI;
    private javax.swing.JMenuItem duplicateSMI;
    private javax.swing.JMenu editMenu;
    private javax.swing.JMenuItem exitFMI;
    private javax.swing.JMenuItem exportFMI;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JMenuItem importFMI;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JLabel libraryLabel;
    private javax.swing.JScrollPane libraryPane;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem newSMI;
    private javax.swing.JTree nodeTree;
    private javax.swing.JLabel overviewLabel;
    private javax.swing.JScrollPane overviewPane;
    private javax.swing.JMenuItem reverseEMI;
    private javax.swing.JMenuItem saveFMI;
    private javax.swing.JLabel slideContentLabel;
    private javax.swing.JScrollPane slideContentPane;
    private javax.swing.JLabel slideInfoLabel;
    private javax.swing.JScrollPane slideInfoPane;
    private javax.swing.JTextField slideInfoTagBox;
    private javax.swing.JMenu slideMenu;
    // End of variables declaration//GEN-END:variables
}
